package com.fbs.job.admin.core.thread;

import com.fbs.job.admin.core.config.FbsJobAdminConfig;
import com.fbs.job.admin.core.entity.FbsJobInfo;
import com.fbs.job.admin.core.entity.FbsJobLog;
import com.fbs.job.admin.core.enums.TriggerTypeEnum;
import com.fbs.job.admin.mapper.FbsJobLogMapper;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class JobFailHandleHelper {
    private static Logger logger = LoggerFactory.getLogger(JobFailHandleHelper.class);

    private static JobFailHandleHelper instance = new JobFailHandleHelper();
    public static JobFailHandleHelper getInstance(){
        return instance;
    }

    private Thread handlerThread;
    private volatile boolean toStop = false;

    private FbsJobLogMapper fbsJobLogMapper= FbsJobAdminConfig.getAdminConfig().getFbsJobLogMapper();

    public void start(){
        handlerThread = new Thread(new Runnable() {
            @Override
            public void run() {
                   while (!toStop){
                        try {
                            List<Long> failLogIds = fbsJobLogMapper.findFailJobLogIds(1000);
                            if (CollectionUtils.isNotEmpty(failLogIds)){
                                for (Long failLogId : failLogIds) {
                                    // lock log 防止别的线程处理 导致重复
                                    int lockRet = fbsJobLogMapper.updateAlarmStatus(failLogId, 0, -1);
                                    if (lockRet < 1) {
                                        continue;
                                    }
                                    FbsJobLog log = fbsJobLogMapper.getById(failLogId);
                                    FbsJobInfo info = FbsJobAdminConfig.getAdminConfig().getFbsJobInfoMapper().getById(log.getJobId());
                                    // 1、fail retry monitor
                                    if (log.getExecutorFailRetryCount() > 0) {
                                        JobTriggerPoolHelper.trigger(log.getJobId(), TriggerTypeEnum.RETRY, (log.getExecutorFailRetryCount()-1), log.getExecutorShardingParam(), log.getExecutorParam(), null);
                                        String retryMsg = "<br><br><span style=\"color:#F39C12;\" > >>>>>>>>>>>"+ "失败重试触发" +"<<<<<<<<<<< </span><br>";
                                        log.setTriggerMsg(log.getTriggerMsg() + retryMsg);
                                        FbsJobAdminConfig.getAdminConfig().getFbsJobLogMapper().updateTriggerInfo(log);
                                    }

                                    // 2、fail alarm monitor
                                    int newAlarmStatus = 0;		// 告警状态：0-默认、-1=锁定状态、1-无需告警、2-告警成功、3-告警失败
                                    if (info != null) {
                                        boolean alarmResult = FbsJobAdminConfig.getAdminConfig().getJobAlarmer().alarm(info, log);
                                        newAlarmStatus = alarmResult?2:3;
                                    } else {
                                        newAlarmStatus = 1;
                                    }

                                    fbsJobLogMapper.updateAlarmStatus(failLogId, -1, newAlarmStatus);

                                }
                            }
                        }catch (Exception e ){
                            if (!toStop) {
                                logger.error(">>>>>>>>>>> fbs-job, job fail monitor thread error:{}", e);
                            }
                        }

                       try {
                           TimeUnit.SECONDS.sleep(10);
                       } catch (Exception e) {
                           if (!toStop) {
                               logger.error(e.getMessage(), e);
                           }
                       }
                   }
                logger.info(">>>>>>>>>>> fbs-job, job fail handle thread stop");

            }
        });

        handlerThread.setDaemon(true);
        handlerThread.setName("fbs-job, admin JobFailHandleHelper");
        handlerThread.start();
    }

    public void toStop(){
        toStop = true;
        // interrupt and wait
        handlerThread.interrupt();
        try {
            handlerThread.join();
        } catch (InterruptedException e) {
            logger.error(e.getMessage(), e);
        }
    }

}
